﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UMedia = umbraco.cms.businesslogic.media.Media;
using UMediaType = umbraco.cms.businesslogic.media.MediaType;
using System.Web;
using System.IO;
using System.Web.Hosting;
using System.ServiceModel.Activation;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.property;

namespace USTF.Media.MediaService.UmbracoDefault
{
    /// <summary>
    /// Retreives media items only as Image or Folder docs under the Media section of Umbraco. Assumes umbracoFile property.
    /// </summary>
    [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
    public class UmbracoDefaultImageMediaService : IUSTFMediaService
    {

        #region IUSTFMediaService Members

        /// <summary>
        /// Retreives all media items as children of a specific node, or all direct root media items if no valid Parent is specified.
        /// </summary>
        /// <param name="parentId"></param>
        /// <returns></returns>
        public IEnumerable<MediaItem> GetMediaItems(int parentId)
        {
            if (parentId < 1)
            {
                return UMedia.GetRootMedias().Select(umbmedia => umbmedia.ToMediaItem());
            }

            UMedia parent = null;
            try
            {
                parent = new UMedia(parentId);
            }
            catch { }

            if (parent != null && parent.Children != null && parent.Children.Length > 0)
            {
                return parent.Children.Select(umbmedia => umbmedia.ToMediaItem());
            }
            else
                return new List<MediaItem>();

            
        }

        public bool Delete(int id)
        {
            throw new NotImplementedException();
        }

        public int Create(MediaItem item)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Retreives the byte[] data of the file specified at the uploaded location for the Image
        /// </summary>
        /// <param name="item"></param>
        /// <param name="contentsInstance"></param>
        /// <returns></returns>
        public byte[] GetData(MediaItem item, string contentsInstance)
        {
            //get image path
            var umbracoItem = new UMedia(item.ID);
            var localPath = HostingEnvironment.MapPath(umbracoItem.getProperty("umbracoFile").Value.ToString());
            

            //read file and return data
            return File.ReadAllBytes(localPath);
        }

        public void SaveData(MediaItem item, string contentsInstance, byte[] contents)
        {
            //new or existing?
            bool isNewItem = (item.ID < 0);
            UMedia umbracoDataItem;
            
            //create new item or get existing item
            if (isNewItem)
            {
                //try to get parent id, otherwise save in root
                int parentId =
                    item.Properties.SafeGetInt(UmbracoFieldMediaItemProperties.ParentId,
                        UMedia.GetRootMedias().First().Id  //ugly GetRootMedias
                            );

                umbracoDataItem = CreateUmbracoMedia(item, parentId);
            }
            else
            {
                try
                {
                    umbracoDataItem = new UMedia(item.ID);
                }
                catch (Exception ex)
                {
                    throw new Exception("Error opening media item (ID:" + item.ID.ToString() + ") - " + ex.Message, ex);
                }
            }

            //validate
            //we need umbraco media item to continue
            if (umbracoDataItem == null)
                throw new Exception("Could not find or create Umbraco Media Item");

            //since this is a 'default' implementation to support the
            //Umbraco Media section with the default Image data-type
            //we just save the image to the hard-coded path
            //and change the umbracoFile path to the saved image path

            //dir location is:
            //media/[file property id]/[filename]

            var fileProperty = umbracoDataItem.getProperty("umbracoFile");
            var extensionProperty = umbracoDataItem.getProperty("umbracoExtension");
            var byteCountProperty = umbracoDataItem.getProperty("umbracoBytes");

            string virtualPath = String.Format("/media/{0}/", fileProperty.Id.ToString());
            string fileDir = HttpContext.Current.Server.MapPath(virtualPath);

            //ensure path exists
            Directory.CreateDirectory(fileDir);

            //save data (ok to rewrite, as directory assumes unique for this media item)
            //TODO: don't default to jpeg!
            string fileName = item.Properties.SafeGetValue(CommonFieldNames.FILENAME, Guid.NewGuid().ToString() + ".jpg");
            string filePath = Path.Combine(fileDir, fileName);
            File.WriteAllBytes(filePath, contents);

            //save file details to umbraco properties
            string virtualFilePath = virtualPath + "/" + fileName;
            string fileExtension = Path.GetExtension(filePath).Replace(".", String.Empty);
            fileProperty.Value = virtualFilePath;
            extensionProperty.Value = fileExtension;
            byteCountProperty.Value = contents.Length;

        }

        private UMedia CreateUmbracoMedia(MediaItem mediaData, int parentId)
        {
            switch (mediaData.MediaType)
            {
                case MediaType.Image:
                    return CreateUmbracoImage(mediaData,parentId);
                    break;
                case MediaType.Folder:
                    break;
                default:
                    break;
            }

            throw new NotSupportedException("Service does not support provided Media Type");
            
        }

        private UMedia CreateUmbracoImage(MediaItem mediaData, int parentId)
        {
            //get image media type
            var imageMediaType = UMediaType.GetByAlias("Image");

            //create new umbraco object
            string defaultTitle = "no-title";
            UMedia result = UMedia.MakeNew(mediaData.Properties.SafeGetValue(CommonFieldNames.TITLE,defaultTitle),
                imageMediaType,
                User.GetUser(0),
                parentId);

            //return
            return result;
        }
        #endregion
    }
}
